﻿// Decompiled with JetBrains decompiler
// Type: DnProcessSimulateCommands.ExportToRTR.CUiExportToRTRContentRobotCollisionSetsDataGenerator
// Assembly: DnProcessSimulateCommands, Version=2402.0.0.890, Culture=neutral, PublicKeyToken=null
// MVID: A885D881-AEDF-447E-852A-6F13102E089C
// Assembly location: C:\Program Files\Tecnomatix_2402\eMPower\DotNetCommands\DnProcessSimulateCommands.dll

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Tecnomatix.Engineering;


namespace DnProcessSimulateCommands.ExportToRTR{

internal class CUiExportToRTRContentRobotCollisionSetsDataGenerator
{
  private TxCollisionPair m_collisionPair;
  private Dictionary<ITxRobot, HashSet<ITxObject>>[] m_robotOwnObjectList = new Dictionary<ITxRobot, HashSet<ITxObject>>[2]
  {
    new Dictionary<ITxRobot, HashSet<ITxObject>>(),
    new Dictionary<ITxRobot, HashSet<ITxObject>>()
  };
  private HashSet<ITxObject>[] m_robotCollideWithObjectList = new HashSet<ITxObject>[2]
  {
    new HashSet<ITxObject>(),
    new HashSet<ITxObject>()
  };
  private HashSet<ITxObject> m_handledObjects = new HashSet<ITxObject>();
  private int m_handledSide;

  private Dictionary<ITxObject, TxRobot> ObjectsWith3DOfRobot { get; } = new Dictionary<ITxObject, TxRobot>();

  private HashSet<ITxObject> ObjectsWith3D { get; } = new HashSet<ITxObject>();

  private Dictionary<ITxRobot, CApExportToRTRRobotCollisionSetsData> CollisionSetsData { set; get; }

  public CUiExportToRTRContentRobotCollisionSetsDataGenerator(
    Dictionary<ITxObject, TxRobot> objectsWith3DOfRobot,
    HashSet<ITxObject> objectsWith3D,
    TxCollisionPair pair,
    Dictionary<ITxRobot, CApExportToRTRRobotCollisionSetsData> collisionSetsData)
  {
    this.ObjectsWith3DOfRobot = objectsWith3DOfRobot;
    this.ObjectsWith3D = objectsWith3D;
    this.m_collisionPair = pair;
    this.CollisionSetsData = collisionSetsData;
  }

  internal void Execute()
  {
    this.ComputeRobotLists(this.m_collisionPair.FirstList, this.m_collisionPair.SecondList);
    this.m_handledSide = 1;
    this.m_handledObjects.Clear();
    this.ComputeRobotLists(this.m_collisionPair.SecondList, this.m_collisionPair.FirstList);
    this.m_handledSide = 0;
    this.UpdateCollisionSetsData();
    this.m_handledSide = 1;
    this.UpdateCollisionSetsData();
  }

  private void ComputeRobotLists(TxObjectList robotList, TxObjectList objectList)
  {
    HashSet<ITxObject> itxObjectSet = new HashSet<ITxObject>();
    foreach (ITxObject robot in (Collection<ITxObject>) robotList)
      this.ComputeObjectToAddToRobotOwnList(robot);
    foreach (ITxObject itxObject in (Collection<ITxObject>) objectList)
      this.ComputeObjectToAddToRobotCollideWithList(itxObject);
  }

  private void ComputeObjectToAddToRobotOwnList(ITxObject obj)
  {
    if (!CApExportToRTRUtils.IsVisible(obj as ITxDisplayableObject))
      return;
    if (obj is TxRobot txRobot)
      this.AddKinObjToRobotOwnList(txRobot, (ITxObject) txRobot);
    else if (this.ObjectsWith3DOfRobot.TryGetValue(obj, out txRobot))
    {
      if (obj is TxKinematicLink)
      {
        this.AddLinkToRobotOwnList(obj, (ITxRobot) txRobot);
      }
      else
      {
        this.AddObjectToRobotOwnList(obj, (ITxRobot) txRobot);
        if (!(obj is TxServoGun kinObj))
          return;
        this.AddKinObjToRobotOwnList(txRobot, (ITxObject) kinObj);
      }
    }
    else
    {
      if (!(obj is ITxObjectCollection objectCollection))
        return;
      foreach (ITxObject itxObject in (Collection<ITxObject>) (objectCollection?.GetDirectDescendants((ITxTypeFilter) new TxTypeFilter(typeof (ITxObjectCollection))) ?? new TxObjectList()))
        this.ComputeObjectToAddToRobotOwnList(itxObject);
    }
  }

  private void AddKinObjToRobotOwnList(TxRobot robot, ITxObject kinObj)
  {
    TxObjectList txObjectList1;
    if (!(kinObj is ITxObjectCollection objectCollection))
    {
      txObjectList1 = (TxObjectList) null;
    }
    else
    {
      TxTypeFilter txTypeFilter = new TxTypeFilter(new Type[2]
      {
        typeof (ITxComponent),
        typeof (TxKinematicLink)
      });
      txObjectList1 = objectCollection.GetAllDescendants((ITxTypeFilter) txTypeFilter);
    }
    if (txObjectList1 == null)
      txObjectList1 = new TxObjectList();
    TxObjectList txObjectList2 = txObjectList1;
    int count = this.m_handledObjects.Count;
    foreach (ITxObject itxObject in (Collection<ITxObject>) txObjectList2)
    {
      if (this.ObjectsWith3DOfRobot.ContainsKey(itxObject))
      {
        if (itxObject is TxKinematicLink)
          this.AddLinkToRobotOwnList(itxObject, (ITxRobot) robot);
        else
          this.AddObjectToRobotOwnList(itxObject, (ITxRobot) robot);
      }
    }
    if (this.m_handledObjects.Count <= count)
      return;
    this.m_handledObjects.Add(kinObj);
  }

  private void AddLinkToRobotOwnList(ITxObject link, ITxRobot robot)
  {
    this.AddObjectToRobotOwnList(link, robot);
  }

  private void AddObjectToRobotOwnList(ITxObject obj, ITxRobot robot)
  {
    if (this.m_handledObjects.Contains(obj))
      return;
    Dictionary<ITxRobot, HashSet<ITxObject>> robotOwnObject = this.m_robotOwnObjectList[this.m_handledSide];
    HashSet<ITxObject> itxObjectSet;
    if (!robotOwnObject.TryGetValue(robot, out itxObjectSet))
    {
      itxObjectSet = new HashSet<ITxObject>();
      robotOwnObject.Add(robot, itxObjectSet);
    }
    itxObjectSet.Add(obj);
    this.m_handledObjects.Add(obj);
  }

  private void ComputeObjectToAddToRobotCollideWithList(ITxObject obj)
  {
    int ofCollideWithList = this.CurrentNumberOfCollideWithList;
    this.ComputeObjectToAddToRobotCollideWithListForDescendants(obj);
    if (ofCollideWithList != this.CurrentNumberOfCollideWithList)
      return;
    this.ComputeObjectToAddToRobotCollideWithListForPredecessor(obj);
  }

  private void ComputeObjectToAddToRobotCollideWithListForDescendants(ITxObject obj)
  {
    if (this.m_handledObjects.Contains(obj) || !CApExportToRTRUtils.IsVisible(obj as ITxDisplayableObject))
      return;
    if (this.ObjectsWith3D.Contains(obj))
    {
      this.AddObjectToRobotCollideWithList(obj);
    }
    else
    {
      if (!(obj is ITxObjectCollection objectCollection))
        return;
      foreach (ITxObject directDescendant in (Collection<ITxObject>) objectCollection.GetDirectDescendants((ITxTypeFilter) new TxTypeFilter(typeof (ITxObjectCollection))))
        this.ComputeObjectToAddToRobotCollideWithListForDescendants(directDescendant);
    }
  }

  private void ComputeObjectToAddToRobotCollideWithListForPredecessor(ITxObject obj)
  {
    ITxObjectCollection collection = obj.Collection;
    if (collection == null || this.m_handledObjects.Contains((ITxObject) collection) || collection is TxPhysicalRoot)
      return;
    if (this.ObjectsWith3D.Contains((ITxObject) collection))
    {
      this.AddObjectToRobotCollideWithList((ITxObject) collection);
    }
    else
    {
      if (!(collection is TxBaseGeometryCreationObject))
        return;
      this.ComputeObjectToAddToRobotCollideWithListForPredecessor((ITxObject) collection);
    }
  }

  private void AddObjectToRobotCollideWithList(ITxObject obj)
  {
    this.m_robotCollideWithObjectList[this.m_handledSide].Add(obj);
    this.m_handledObjects.Add(obj);
  }

  private int CurrentNumberOfCollideWithList
  {
    get => this.m_robotCollideWithObjectList[this.m_handledSide].Count;
  }

  private void UpdateCollisionSetsData()
  {
    List<ITxLocatableObject> staticList = new List<ITxLocatableObject>();
    this.m_robotCollideWithObjectList[this.m_handledSide].ToList<ITxObject>().ForEach((Action<ITxObject>) (obj => staticList.Add(obj as ITxLocatableObject)));
    if (staticList.Count <= 0)
      return;
    foreach (KeyValuePair<ITxRobot, HashSet<ITxObject>> keyValuePair in this.m_robotOwnObjectList[this.m_handledSide])
    {
      ITxRobot key = keyValuePair.Key;
      CApExportToRTRRobotCollisionSetsData collisionSetsData;
      if (!this.CollisionSetsData.TryGetValue(key, out collisionSetsData))
      {
        collisionSetsData = new CApExportToRTRRobotCollisionSetsData();
        this.CollisionSetsData.Add(key, collisionSetsData);
      }
      List<ITxLocatableObject> robotList = new List<ITxLocatableObject>();
      keyValuePair.Value.ToList<ITxObject>().ForEach((Action<ITxObject>) (obj => robotList.Add(obj as ITxLocatableObject)));
      collisionSetsData.AddStaticCollisionSets(robotList, staticList);
    }
  }
}
